﻿Imports System

Namespace System.Workflow.ComponentModel
    Friend Class CompensationHandlingFilter
        Inherits ActivityExecutionFilter
        Implements IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs)
        ' Methods
        Public Overrides Function Compensate(ByVal activity As Activity, ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            executionContext.Activity.HoldLockOnStatusChange(Me)
            Return MyBase.NextActivityExecutorInChain(activity).Compensate(activity, executionContext)
        End Function

        Friend Shared Function GetCompensationHandler(ByVal activityWithCompensation As Activity) As Activity
            Dim activity2 As CompositeActivity = [TryCast](activityWithCompensation,CompositeActivity)
            If (Not activity2 Is Nothing) Then
                Dim activity3 As Activity
                For Each activity3 In DirectCast(activity2, ISupportAlternateFlow).AlternateFlowActivities
                    If TypeOf activity3 Is CompensationHandlerActivity Then
                        Return activity3
                    End If
                Next
            End If
            Return Nothing
        End Function

        Private Sub System.Workflow.ComponentModel.IActivityEventListener<System.Workflow.ComponentModel.ActivityExecutionStatusChangedEventArgs>.OnEvent(ByVal sender As Object, ByVal e As ActivityExecutionStatusChangedEventArgs) Implements IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs).OnEvent
            Dim context As ActivityExecutionContext = [TryCast](sender,ActivityExecutionContext)
            If (context Is Nothing) Then
                Throw New ArgumentException("sender")
            End If
            If (e.Activity Is context.Activity) Then
                If (context.Activity.HasPrimaryClosed AndAlso Not CBool(context.Activity.GetValue(CompensationHandlingFilter.CompensateProcessedProperty))) Then
                    context.Activity.SetValue(CompensationHandlingFilter.CompensateProcessedProperty, True)
                    If (context.Activity.ExecutionResult <> ActivityExecutionResult.Compensated) Then
                        context.Activity.ReleaseLockOnStatusChange(Me)
                    Else
                        Dim compensationHandler As Activity = CompensationHandlingFilter.GetCompensationHandler(context.Activity)
                        If (Not compensationHandler Is Nothing) Then
                            compensationHandler.RegisterForStatusChange(Activity.ClosedEvent, Me)
                            context.ExecuteActivity(compensationHandler)
                        ElseIf Not CompensationUtils.TryCompensateLastCompletedChildActivity(context, context.Activity, Me) Then
                            context.Activity.ReleaseLockOnStatusChange(Me)
                        End If
                    End If
                End If
            ElseIf (TypeOf e.Activity Is CompensationHandlerActivity AndAlso (e.ExecutionStatus = ActivityExecutionStatus.Closed)) Then
                e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, Me)
                context.Activity.ReleaseLockOnStatusChange(Me)
            ElseIf (e.ExecutionStatus = ActivityExecutionStatus.Closed) Then
                e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, Me)
                If Not CompensationUtils.TryCompensateLastCompletedChildActivity(context, context.Activity, Me) Then
                    context.Activity.ReleaseLockOnStatusChange(Me)
                End If
            End If
        End Sub


        ' Fields
        Public Shared CompensateProcessedProperty As DependencyProperty = DependencyProperty.RegisterAttached("CompensateProcessed", GetType(Boolean), GetType(CompensationHandlingFilter), New PropertyMetadata(False))
        Friend Shared LastCompensatedOrderIdProperty As DependencyProperty = DependencyProperty.RegisterAttached("LastCompensatedOrderId", GetType(Integer), GetType(CompensationHandlingFilter), New PropertyMetadata(False))
    End Class
End Namespace

